package helper

import (
	"crypto/md5"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/jordan-wright/email"
	uuid "github.com/satori/go.uuid"
	"math/rand"
	"net/smtp"
	"os"
	"time"
)

type UserClaims struct {
	UserID   string `json:"user_id"`
	Username string `json:"username"`
	IsAdmin  int    `json:"is_admin"`
	jwt.StandardClaims
}

// 生成md5
func GetMd5(s string) string {
	return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}

// 生成token
func TestGenerateToken(userid, username string, isAdmin int) (string, error) {
	claims := UserClaims{
		UserID:         userid,
		Username:       username,
		IsAdmin:        isAdmin,
		StandardClaims: jwt.StandardClaims{},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString([]byte("gin_gorm_oj_key"))
	if err != nil {
		return "", err
	}
	return tokenString, nil
}

// 解析token
func TestParseToken(tokenString string) (*UserClaims, error) {
	UserClaims := &UserClaims{}
	token, err := jwt.ParseWithClaims(tokenString, UserClaims, func(token *jwt.Token) (interface{}, error) {
		return []byte("gin_gorm_oj_key"), nil
	})
	if err != nil {
		return nil, err
	}
	if !token.Valid {
		return nil, fmt.Errorf("invalid token", err)
	}
	return UserClaims, nil
}

// 发送验证码
func SendEmail(toEmail, code string) error {
	e := email.NewEmail()
	e.From = ".. <1063716148@qq.com>"
	e.To = []string{toEmail}
	e.Subject = "验证码"
	e.HTML = []byte(fmt.Sprintf("<h1>您的验证码为: %s</h1>", code))
	err := e.Send("smtp.qq.com:587", smtp.PlainAuth("", "1063716148@qq.com", "vtsycmbcnjecbbhf", "smtp.qq.com"))
	if err != nil {
		return err
	}
	return nil
}

// 生成唯一码
func GetUUID() string {
	return uuid.NewV4().String()
}

// 生成随机验证码
func GetCode() string {
	rand.Seed(time.Now().UnixNano()) // 设置随机种子
	code := fmt.Sprintf("%06d", rand.Intn(1000000))
	return code
}

// 代码保存
func SaveCode(code []byte) (string, error) {
	dirName := "./code/" + GetUUID()
	path := dirName + "/main.go"
	err := os.Mkdir(dirName, 0755)
	if err != nil {
		return "", err
	}
	f, err := os.Create(path)
	if err != nil {
		return "", err
	}
	defer f.Close()
	_, err = f.Write(code)
	return path, err
}
